package com.ikingtech.platform.business.message.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.data.mybatisplus.helper.base.BaseTenantController;
import com.ikingtech.framework.sdk.message.model.MessageSubscriberDTO;
import com.ikingtech.framework.sdk.message.model.MessageSubscriberDataDefinitionDTO;
import com.ikingtech.framework.sdk.message.model.MessageSubscriberQueryParamDTO;
import com.ikingtech.framework.sdk.message.model.MessageSubscriberSendUrlDTO;
import com.ikingtech.framework.sdk.utils.Tools;
import com.ikingtech.framework.sdk.web.annotation.ApiController;
import com.ikingtech.platform.business.message.entity.MessageSubscriberDO;
import com.ikingtech.platform.business.message.entity.MessageSubscriberDataDefinitionDO;
import com.ikingtech.platform.business.message.entity.MessageSubscriberSendUrlDO;
import com.ikingtech.platform.business.message.service.repository.MessageSubscriberDataDefinitionRepository;
import com.ikingtech.platform.business.message.service.repository.MessageSubscriberRepository;
import com.ikingtech.platform.business.message.service.repository.MessageSubscriberSendUrlRepository;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @author tie yan
 */
@ApiController(value = "/message/subscriber", name = "消息中心-订阅方管理", description = "消息中心-订阅方管理")
public class MessageSubscriberController extends BaseTenantController<MessageSubscriberDTO, MessageSubscriberDO, MessageSubscriberQueryParamDTO> {

    private final MessageSubscriberSendUrlRepository sendUrlRepo;

    private final MessageSubscriberDataDefinitionRepository dataDefinitionRepo;

    public MessageSubscriberController(MessageSubscriberRepository repo,
                                       MessageSubscriberSendUrlRepository sendUrlRepo,
                                       MessageSubscriberDataDefinitionRepository dataDefinitionRepo) {
        super(repo, MessageSubscriberDTO.class, MessageSubscriberDO.class);
        this.sendUrlRepo = sendUrlRepo;
        this.dataDefinitionRepo = dataDefinitionRepo;
    }

    @Override
    public void afterSave(MessageSubscriberDTO subscriber, MessageSubscriberDO subscriberEntity) {
        this.save(subscriber, subscriberEntity);
    }

    @Override
    public void afterDelete(String subscriberId) {
        this.sendUrlRepo.remove(Wrappers.<MessageSubscriberSendUrlDO>lambdaQuery()
                .eq(MessageSubscriberSendUrlDO::getSubscriberId, subscriberId));
        this.dataDefinitionRepo.remove(Wrappers.<MessageSubscriberDataDefinitionDO>lambdaQuery()
                .eq(MessageSubscriberDataDefinitionDO::getSubscriberId, subscriberId));
    }

    @Override
    public void afterUpdate(MessageSubscriberDTO subscriber, MessageSubscriberDO subscriberEntity) {
        this.sendUrlRepo.remove(Wrappers.<MessageSubscriberSendUrlDO>lambdaQuery()
                .eq(MessageSubscriberSendUrlDO::getSubscriberId, subscriberEntity.getId()));
        this.dataDefinitionRepo.remove(Wrappers.<MessageSubscriberDataDefinitionDO>lambdaQuery()
                .eq(MessageSubscriberDataDefinitionDO::getSubscriberId, subscriberEntity.getId()));
        this.save(subscriber, subscriberEntity);
    }

    private void save(MessageSubscriberDTO subscriber, MessageSubscriberDO subscriberEntity) {
        List<MessageSubscriberDataDefinitionDO> dataDefinitionEntities = new ArrayList<>();
        this.sendUrlRepo.saveBatch(Tools.Coll.convertList(subscriber.getSendUrls(), sendUrl -> {
            MessageSubscriberSendUrlDO sendUrlEntity = Tools.Bean.copy(sendUrl, MessageSubscriberSendUrlDO.class);
            sendUrlEntity.setId(Tools.Id.uuid());
            sendUrlEntity.setTenantCode(Me.tenantCode());
            sendUrlEntity.setSubscriberId(subscriberEntity.getId());
            dataDefinitionEntities.addAll(Tools.Coll.convertList(sendUrl.getDataDefinitions(), dataDefinition -> {
                MessageSubscriberDataDefinitionDO dataDefinitionEntity = Tools.Bean.copy(dataDefinition, MessageSubscriberDataDefinitionDO.class);
                dataDefinitionEntity.setId(Tools.Id.uuid());
                dataDefinitionEntity.setTenantCode(Me.tenantCode());
                dataDefinitionEntity.setSendUrlId(sendUrlEntity.getId());
                dataDefinitionEntity.setSubscriberId(subscriberEntity.getId());
                return dataDefinitionEntity;
            }));
            return sendUrlEntity;
        }));
        if (Tools.Coll.isNotBlank(dataDefinitionEntities)) {
            this.dataDefinitionRepo.saveBatch(dataDefinitionEntities);
        }
    }

    @Override
    public List<String> beforeQuery(MessageSubscriberQueryParamDTO queryParam) {
        return Tools.Str.isNotBlank(queryParam.getSendUrl()) ?
                this.sendUrlRepo.listObjs(Wrappers.<MessageSubscriberSendUrlDO>lambdaQuery()
                        .select(MessageSubscriberSendUrlDO::getSubscriberId)
                        .like(MessageSubscriberSendUrlDO::getSendUrl, queryParam.getSendUrl())) :
                Collections.emptyList();
    }

    @Override
    public List<MessageSubscriberDTO> modelConvert(List<MessageSubscriberDO> entities) {
        List<String> subscriberIds = Tools.Coll.convertList(entities, MessageSubscriberDO::getId);
        List<MessageSubscriberSendUrlDO> sendUrlEntities = this.sendUrlRepo.list(Wrappers.<MessageSubscriberSendUrlDO>lambdaQuery()
                .in(MessageSubscriberSendUrlDO::getSubscriberId, subscriberIds));
        Map<String, List<MessageSubscriberSendUrlDO>> sendUrlMap = Tools.Coll.convertGroup(sendUrlEntities,
                MessageSubscriberSendUrlDO::getSubscriberId);

        List<MessageSubscriberDataDefinitionDO> dataDefinitionEntities = this.dataDefinitionRepo.list(Wrappers.<MessageSubscriberDataDefinitionDO>lambdaQuery()
                .in(MessageSubscriberDataDefinitionDO::getSubscriberId, subscriberIds));
        Map<String, List<MessageSubscriberDataDefinitionDO>> dataDefinitionMap = Tools.Coll.convertGroup(dataDefinitionEntities,
                MessageSubscriberDataDefinitionDO::getSubscriberId);

        return Tools.Coll.convertList(entities,
                entity -> this.modelConvert(entity,
                        sendUrlMap.get(entity.getId()),
                        dataDefinitionMap.get(entity.getId())));
    }

    @Override
    public MessageSubscriberDTO modelConvert(MessageSubscriberDO entity) {
        List<MessageSubscriberSendUrlDO> sendUrlEntities = this.sendUrlRepo.list(Wrappers.<MessageSubscriberSendUrlDO>lambdaQuery()
                .eq(MessageSubscriberSendUrlDO::getSubscriberId, entity.getId()));
        List<MessageSubscriberDataDefinitionDO> dataDefinitionEntities = this.dataDefinitionRepo.list(Wrappers.<MessageSubscriberDataDefinitionDO>lambdaQuery()
                .eq(MessageSubscriberDataDefinitionDO::getSubscriberId, entity.getId()));
        return this.modelConvert(entity, sendUrlEntities, dataDefinitionEntities);
    }

    private MessageSubscriberDTO modelConvert(MessageSubscriberDO entity, List<MessageSubscriberSendUrlDO> sendUrlEntities, List<MessageSubscriberDataDefinitionDO> dataDefinitionEntities) {
        Map<String, List<MessageSubscriberDataDefinitionDO>> dataDefinitionMap = Tools.Coll.convertGroup(dataDefinitionEntities, MessageSubscriberDataDefinitionDO::getSendUrlId);
        MessageSubscriberDTO subscriber = Tools.Bean.copy(entity, MessageSubscriberDTO.class);
        subscriber.setSendUrls(Tools.Coll.convertList(sendUrlEntities, sendUrlEntity -> {
            MessageSubscriberSendUrlDTO sendUrl = Tools.Bean.copy(sendUrlEntity, MessageSubscriberSendUrlDTO.class);
            sendUrl.setDataDefinitions(Tools.Coll.convertList(dataDefinitionMap.get(sendUrlEntity.getId()),
                    dataDefinitionEntity -> Tools.Bean.copy(dataDefinitionEntity, MessageSubscriberDataDefinitionDTO.class)));
            return sendUrl;
        }));
        return subscriber;
    }
}
